package com.shyt.filter;

import com.alibaba.fastjson.JSON;
import com.shyt.dao.RecordLogAspectVo;
import com.shyt.filter.annotation.RecordLogsAspectAt;
import com.shyt.impl.RecordLogAspectImpl;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.UUID;

/**
 * author:
 * 埋点切面
 */
@Aspect
@Component
@Slf4j
public class RecordLogAspect {

    @Resource
    RecordLogAspectImpl recordLogAspectImpl;
    /**
     * 排除敏感属性字段
     */
//    public static final String[] EXCLUDE_PROPERTIES =
//            { "password", "oldPassword", "newPassword", "confirmPassword" };




    //@Around("controllerAspectse()")
    @Around(value = "execution(* com.shyt.api.*.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        RecordLogAspectVo recordLogAspectVo = new RecordLogAspectVo();
        // 获取方法签名
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        RecordLogsAspectAt recordLogsAspect =
                signature.getMethod().getAnnotation(RecordLogsAspectAt.class);//注解

        //是否开启日志打印
        //Boolean isLog = recordLogsAspect.isLog();
        Long startTime = System.currentTimeMillis();

        recordLogAspectVo.setStartTime(
                new SimpleDateFormat("yyyy-MM-dd HH:MM:SS").format(new Date()));

        try {
            //开始打印日志
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            HttpSession session = request.getSession();
            String api = pjp.getTarget().getClass().getName() + "." + pjp.getSignature().getName();
            log.info("请求API：{} " , api);
            recordLogAspectVo.setMethod(api);

            String methodDescription = getControllerMethodDescription(pjp);
            log.info("方法描述：{}" , methodDescription);
            recordLogAspectVo.setDescription(methodDescription);

            String ipAddress = InetAddress.getLocalHost().toString().substring(InetAddress.getLocalHost().toString().lastIndexOf("/") + 1);
            log.info("请求ip：{}" , ipAddress);
            recordLogAspectVo.setIpAddress(ipAddress);

            String hostName = InetAddress.getLocalHost().getHostName();
            log.info("机器名：{}" , hostName);
            recordLogAspectVo.setHostName(hostName);

            Enumeration<?> enu = request.getParameterNames();
            String params = "{";
            while (enu.hasMoreElements()) {
                String paraName = (String) enu.nextElement();
                params += "\"" + paraName + "\":\"" + request.getParameter(paraName) + "\",";
            }
            String methodParams = params + "}";
            String substring = methodParams.substring(0, methodParams.length() - 2);
            substring = substring + "}";
            log.info("方法参数：{}" , substring);
            recordLogAspectVo.setReqParams(substring);

            StringBuffer url = request.getRequestURL();
            log.info("URL：" + url);
            recordLogAspectVo.setUrl(String.valueOf(url));

        } catch (Exception e) {
            log.error("错误信息：{}", e.getMessage());

        }

        Object proceed = pjp.proceed();
        String result = JSON.toJSONString(proceed);
        log.info("==============环切方法执行完成==============");

        Long endTime = System.currentTimeMillis();
        recordLogAspectVo.setTimeSpend((endTime - startTime) / 1000 + "s");
        recordLogAspectVo.setEndTime(
                new SimpleDateFormat("yyyy-MM-dd HH:MM:SS").format(new Date()));
        recordLogAspectVo.setPkId(UUID.randomUUID().toString() +
                new SimpleDateFormat("yyyy-MM-dd HH:MM:SS").format(new Date()));
        ArrayList<RecordLogAspectVo> recordLogAspectVos = new ArrayList<>();
        recordLogAspectVos.add(recordLogAspectVo);
        recordLogAspectImpl.insertBatch(recordLogAspectVos);
        //recordLogAspectImpl.insertRecordLogAspect(recordLogAspectVo);
        //信息入库
        return proceed;
    }


    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     */
    public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();//目标方法名
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String description = "";
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description = method.getAnnotation(RecordLogsAspectAt.class).description();
                    break;
                }
            }
        }
        return description;
    }

}
